using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

// string encoding complete

namespace csammisrun.OscarLib.Utility
{
    /// <summary>
    /// Provides static methods for processing messages in SNAC family 0x0010 -- Server-side buddy icons
    /// </summary>
    internal static class SNAC10
    {
        /// <summary>
        /// Uploads the client's own icon -- SNAC(10,02)
        /// </summary>
        /// <param name="sess">A <see cref="Session"/> object</param>
        public static void UploadIcon(Session sess)
        {
            string filename = sess.UploadIconFilename;
            if (filename == "") // possibly this means we should remove the SSI item
            {
                return;
            }

            StreamReader sr = null;
            int index = 0;
            byte[] buffer = null;
            try
            {
                sr = new StreamReader(filename);
                buffer = new byte[4 + sr.BaseStream.Length];
                Marshal.InsertUshort(buffer, 0x0001, ref index);
                Marshal.InsertUshort(buffer, (ushort) sr.BaseStream.Length, ref index);

                while (index < buffer.Length)
                    index += sr.BaseStream.Read(
                        buffer, index, buffer.Length - index);
            }
            catch (Exception)
            {
                sess.OnBuddyIconUploadFailed("Couldn't read " + filename);
                return;
            }
            finally
            {
                if (sr != null)
                    sr.Close();
            }

            SNACHeader sh = new SNACHeader();
            sh.FamilyServiceID = (ushort) SNACFamily.SSBIService;
            sh.FamilySubtypeID = (ushort) SSBIService.UploadIconRequest;
            sh.Flags = 0x0000;
            sh.RequestID = Session.GetNextRequestID();

            DataPacket dp = new DataPacket(buffer);
            dp.ParentSession = sess;
            dp.SNAC = sh;
            SNACFunctions.BuildFLAP(dp);
        }

        /// <summary>
        /// Processes a response to the client's icon upload -- SNAC(10,03)
        /// </summary>
        /// <param name="dp">A <see cref="DataPacket"/> object</param>
        public static void ProcessUploadIconResponse(DataPacket dp)
        {
            if (dp.Data.GetByteCount() == 0x0015)
            {
                dp.ParentSession.OnBuddyIconUploadCompleted();
            }
            else
            {
                // The only time I've ever actually seen this happen is when the
                // data was out of range for the buddy icon servers, but IconVerifier
                // should take care of that instance.
                dp.ParentSession.OnBuddyIconUploadFailed(
                    "Uploaded data did not hash correctly");
            }
        }

        /// <summary>
        /// Requests a remote client's icon for download -- SNAC(10,04)
        /// </summary>
        /// <param name="sess">A <see cref="Session"/> object</param>
        /// <param name="screenname">The screenname of the remote client</param>
        /// <param name="icon">The <see cref="IconInfo"/> received in SNAC(03,0B)</param>
        public static void RequestIcon(Session sess, string screenname, IconInfo icon)
        {
            SNACHeader sh = new SNACHeader();
            sh.FamilyServiceID = (ushort) SNACFamily.SSBIService;
            sh.FamilySubtypeID = (ushort) SSBIService.AIMBuddyIconRequest;
            sh.Flags = 0x0000;

            DataPacket dp = new DataPacket();
            dp.ParentSession = sess;
            dp.SNAC = sh;
            dp.Data.WriteByte((byte) Encoding.ASCII.GetByteCount(screenname));
            dp.Data.WriteString(screenname, Encoding.ASCII);
            dp.Data.WriteByte(0x01);
            dp.Data.WriteUshort(icon.ID);
            dp.Data.WriteByte(icon.HashType);
            dp.Data.WriteByte((byte) icon.Hash.Length);
            dp.Data.WriteByteArray(icon.Hash);

            SNACFunctions.BuildFLAP(dp);
        }

        /// <summary>
        /// Processes a client's buddy icon sent by the server -- SNAC(10,05)
        /// </summary>
        /// <param name="dp">A <see cref="DataPacket"/> object</param>
        public static void ProcessIconDownload(DataPacket dp)
        {
            // Get all of the data out of the data packet
            string screenname;
            ushort flags;
            byte checksumtype;
            byte[] hash;
            byte[] icon;

            screenname = dp.Data.ReadString(dp.Data.ReadByte(), Encoding.ASCII);
            flags = dp.Data.ReadUshort();
            checksumtype = dp.Data.ReadByte();
            hash = dp.Data.ReadByteArray(dp.Data.ReadByte());
            icon = dp.Data.ReadByteArray(dp.Data.ReadUshort());

            // Check the downloaded icon's checksum
            /*MD5CryptoServiceProvider md5 =
                new MD5CryptoServiceProvider();
            byte[] realhash = md5.ComputeHash(icon);
            for (int i = 0; i < realhash.Length; i++)
            {
                if (realhash[i] != hash[i])
                {
                    dp.ParentSession.OnBuddyIconDownloadFailed(screenname, "Mismatched MD5 checksums");
                    return;
                }
            }*/

            dp.ParentSession.OnBuddyIconDownloadCompleted(screenname, icon);
        }
    }
}